import math
import wx
import wx.lib.platebtn as platebtn
import wx.lib.agw.gradientbutton as gradbtn
import httplib as http
import pyrpclib as rpc
from datetime import datetime
#from reschsrv import Session

import threading

content_mgr = http.ContentManager([http.TextMarshaller(), 
								   http.VarargsMarshaller(http.PickleMarshaller, safe_imports='*')])

class MyWin(wx.Window):
    def __init__(self, parent, id):
        wx.Window.__init__(self, parent, id)
#        self.font = wx.NORMAL_FONT
#        size = self.GetClientSize()
        size = wx.Size(400,400)
        print size
        self.buffer = wx.EmptyBitmap(size.width, size.height)
        self.font = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL, face='Book Antiqua')
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Foo()
    
    def Foo(self):
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        dc.BeginDrawing()
#        dc = wx.BufferedDC(None, self.buffer)
#        dc.SetBackground(wx.Brush('white'))
        dc.Clear()
        dc.SetFont(self.font)
        dc.SetTextBackground('grey')
        dc.SetTextForeground('blue')
        dc.DrawText('Hello world!', 10, 10)
        for row in range(8):
            line = '%02X: '%(row*32) + ''.join(unichr(row*32+col) for col in range(32))
#            print line
            dc.DrawText(line, 10, row*15+30)
        dc.EndDrawing()

    def OnPaint(self, evt):
        print 'OnPaint'
        dc = wx.BufferedPaintDC(self, self.buffer)
        
#----------------------------------------------------------------------

EVT_ASYNC_NOTIFY = wx.PyEventBinder(wx.NewEventType())
#class AsyncNotifyEvent(wx.PyEvent):
#	def __init__(self, callback):
#		wx.PyEvent.__init__(self, eventType=EVT_ASYNC_NOTIFY.typeId)
#		self.callback = callback

class SlidebookEvent(wx.BookCtrlBaseEvent):
	pass

EVT_SLIDEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
EVT_SLIDEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING

class SlideBook(wx.PyControl):
	
	TIMER_INTERVAL = 25   # msecs per update
	TIMER_DELAY = 250.0   # msecs to slide one frame
	CORNER_FACTOR = 0.55
	BORDER_FACTOR = 0.06
	MARGIN_FACTOR = 0.03
	
	def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
				 size=wx.DefaultSize, style=0, name='SlideBook'):
#		style |= wx.CLIP_CHILDREN | wx.TRANSPARENT_WINDOW | wx.BORDER_DEFAULT
		wx.PyControl.__init__(self, parent, id, pos, size, style, wx.DefaultValidator, name)
		self.InheritAttributes()
		self.SetInitialSize()
		self._style = style
		self._imagelst = None
		self._updated = False
		self._items = []
		self._curidx = -1
		self._oldidx = None

		self._bgwnd = wx.StaticBitmap(self)
		self._timer = wx.Timer(self)
		self._lbutn = platebtn.PlateButton(self, style=platebtn.PB_STYLE_NOBG)
		self._lbutn.Raise()
#		self._lbutn.Hide()
		self._rbutn = platebtn.PlateButton(self, style=platebtn.PB_STYLE_NOBG)
		self._rbutn.Raise()
#		self._rbutn.Hide()

		self.Bind(wx.EVT_TIMER, self.OnTimer)
		self.Bind(wx.EVT_SIZE, self.OnSize)
		self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
		self.Bind(wx.EVT_SYS_COLOUR_CHANGED, lambda evt: self.UpdateColours())
		self.Bind(wx.EVT_BUTTON, lambda evt: self.AdvanceSelection(False), self._lbutn)
		self.Bind(wx.EVT_BUTTON, lambda evt: self.AdvanceSelection(True), self._rbutn)

		self.UpdateColours()
		self.UpdateUI()

	def DoLayout(self):
		if not self._updated:
			print "DoLayout", self._updated
			return
		self._updated = False
		l = sum(self.ClientSize) / 2.0
		m = int(round(self.MARGIN_FACTOR * l))
		b = int(round(self.BORDER_FACTOR * l))
		r = b * self.CORNER_FACTOR
		p = m + 2 * b
		s = max(b, 18) - 9
		if self._items:
			n = len(self._items)
			i = -self._curidx
		else:
			n = 1
			i = 0
		if self._style & wx.VERTICAL:
			spacing = self.ClientSize.height - p
			self._spacing = (0, spacing)
			rectpt = wx.Point(m, m + b)
			rectsz = self.ClientSize - (2 * m, p + m)
			self.VirtualSize = (self.ClientSize.width, spacing * n + p)
			self._bgwnd.Position = (0, spacing * i)
			butnpt = wx.Point((self.ClientSize.width - b) / 2, 0)
			butnsz = (s, s/2)
			butninc = (0, self.ClientSize.height - b)
			butnpts = [(0.0, s/2.0), (s, s/2.0), (s/2.0, 0.0)]
		else:
			spacing = self.ClientSize.width - p
			self._spacing = (spacing, 0)
			rectpt = wx.Point(m + b, m)
			rectsz = self.ClientSize - (p + m, 2 * m)
			self.VirtualSize = (spacing * n + p, self.ClientSize.height)
			self._bgwnd.Position = (spacing * i, 0)
			butnpt = wx.Point(0, (self.ClientSize.height - b) / 2)
			butnsz = (s/2, s)
			butninc = (self.ClientSize.width - b, 0)
			butnpts = [(s/2.0, 0.0), (s/2.0, s), (0.0, s/2.0)]
		pagesz = rectsz - (2 * b, 2 * b)
		gradsz = (rectsz.width / 2.0, rectsz.height / 2.0)
		diag = math.hypot(*gradsz)
		print "DoLayout", n, self.ClientSize, self.VirtualSize, self._spacing
		(mgcol, shcol, bdcol, gdcol0, gdcol1, btcol0, btcol1) = self._colors

		bitmap = wx.EmptyBitmap(*self.VirtualSize)
		dc = wx.MemoryDC(bitmap)
		gc = wx.GraphicsContext.Create(dc)
		brush = wx.Brush(mgcol)
		gc.SetBrush(brush)
		gc.DrawRoundedRectangle(0, 0, self.VirtualSize.width, self.VirtualSize.height, 1)
		brush = gc.CreateLinearGradientBrush(0, 0, 0, m, shcol, mgcol)
		gc.SetBrush(brush)
		gc.DrawRectangle(0, 0, self.VirtualSize.width, m)
		shbrush = gc.CreateBrush(wx.Brush(shcol))
		bdpen = gc.CreatePen(wx.Pen(bdcol, 1))
		for page, text, imageid in self._items:
			gc.SetPen(wx.TRANSPARENT_PEN)
			gc.SetBrush(shbrush)
			gc.DrawRoundedRectangle(rectpt.x+4, rectpt.y+4, rectsz.width, rectsz.height, r)
			gc.SetPen(bdpen)
			gradpt = rectpt + gradsz
			brush = gc.CreateRadialGradientBrush(rectpt.x+r/2, rectpt.y+r/2, gradpt.x, gradpt.y, diag, gdcol1, gdcol0)
			gc.SetBrush(brush)
			gc.DrawRoundedRectangle(rectpt.x, rectpt.y, rectsz.width, rectsz.height, r)
			page.SetDimensions(rectpt.x+b, rectpt.y+b, pagesz.width, pagesz.height)
			rectpt += self._spacing
		dc.SelectObject(wx.NullBitmap)
		self._bgwnd.SetBitmap(bitmap)
		self._bgwnd.Refresh()

		for butn in self._lbutn, self._rbutn:
			butn.SetDimensions(butnpt.x, butnpt.y, b, b)
			butnpt += butninc
			bitmap = wx.EmptyBitmap(*butnsz)
			dc = wx.MemoryDC(bitmap)
			dc.Background = wx.Brush(gdcol1)
			dc.Clear()
			gc = wx.GraphicsContext.Create(dc)
			brush = gc.CreateLinearGradientBrush(0, 0, butnsz[0], butnsz[1], btcol0, btcol1)
#			brush = wx.GREEN_BRUSH
			gc.SetBrush(brush)
			if butn is self._rbutn:
				gc.Scale(-1.0, -1.0)
				gc.Translate(-s, -s)
			gc.DrawLines(butnpts)
#			dc.SelectObject(wx.NullBitmap)
#			bitmap.SetMaskColour(gdcol1)
			butn.SetBitmap(bitmap)

#		self._DrawButton(self._lbutn, b)
#		self._lbutn.Position = (0, (self.ClientSize.height - b)/2)
#		self._DrawButton(self._rbutn, b)
#		self._rbutn.Position = (self.ClientSize.width-b, (self.ClientSize.height - b)/2)

		self.UpdateUI()
	
	def _DrawButton(self, btn, size):
		size = max(size, 18.0)
		btn.Size = (size, size)
		size -= 9
		if btn is self._rbutn:
			points = [(size/2.0, 0.0),
					  (size/2.0, size),
					  (size, size/2.0)]
		elif btn is self._lbutn:
			points = [(size/2.0, 0.0),
					  (size/2.0, size),
					  (0.0, size/2.0)]
		bitmap = wx.EmptyBitmap(size, size)
		color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRADIENTINACTIVECAPTION)
		dc = wx.MemoryDC(bitmap)
		dc.SetBackground(wx.Brush(color))
		dc.Clear()
		gc = wx.GraphicsContext.Create(dc)
		brush = gc.CreateLinearGradientBrush(0, 0, size, size, 'black', 'grey')
		gc.SetBrush(brush)
		gc.DrawLines(points)
		del gc
		del dc
		bitmap.SetMaskColour(color)
		btn.SetBitmap(bitmap)

	def UpdateColours(self):
		print "UpdateColours"
		bgcol = self.BackgroundColour
		hicol = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
		gdcol = wx.Colour(0.2*hicol.red + 0.8*bgcol.red, 0.2*hicol.green + 0.8*bgcol.green, 0.2*hicol.blue + 0.8*bgcol.blue)
		gdcol0 = wx.Colour(min(gdcol.red*1.05, 255), min(gdcol.green*1.05, 255), min(gdcol.blue*1.05, 255)) # , wx.ALPHA_OPAQUE)
		gdcol1 = wx.Colour(min(gdcol.red*1.20, 255), min(gdcol.green*1.20, 255), min(gdcol.blue*1.20, 255)) # , wx.ALPHA_OPAQUE)
		mgcol = wx.Colour(255, 255, 240) # ivory
		bdcol = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVEBORDER)
		shcol = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW)
		shcol = wx.Colour(shcol.red, shcol.green, shcol.blue, wx.ALPHA_OPAQUE/3.0)
		btcol0 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
		btcol1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
		self._colors = (mgcol, shcol, bdcol, gdcol0, gdcol1, btcol0, btcol1)

	def UpdateUI(self):
		still = not self._timer.IsRunning()
		print "UpdateUI", still, self._curidx, self._curidx > 0, self._curidx < len(self._items) - 1
		self._lbutn.Show(still and self._curidx > 0)
		self._rbutn.Show(still and self._curidx < len(self._items) - 1)

	def OnSize(self, event):
		print "OnSize", self.ClientSize
		if min(self.ClientSize) > 0:
			self._updated = True
			wx.CallAfter(self.DoLayout)

	def OnTimer(self, event):
		self._curpos += self._incpos
		curpos = self._curpos.Rounded
		self._bgwnd.Move(curpos, wx.SIZE_USE_EXISTING|wx.SIZE_ALLOW_MINUS_ONE)
		if curpos == self._dstpos:
			self._timer.Stop()
			self.UpdateUI()
			if self._oldidx is not None:
				event = SlidebookEvent(EVT_SLIDEBOOK_PAGE_CHANGED.typeId, self.GetId(), self._curidx, self._oldidx)
				self.EventHandler.ProcessEvent(event)
				self._oldidx = None

#	def _OnPaintPage(self, event):
#		dc = wx.PaintDC(event.EventObject)
#		width, height = dc.GetSizeTuple()
#		print '_OnPaintPage!', width, height
#		gc = wx.GraphicsContext.Create(dc)
#		brush1 = gc.CreateLinearGradientBrush(0, 0, width, height, 'tan', 'grey')
#		gc.SetBrush(brush1)
#		gc.DrawRoundedRectangle(0,0,width, height,5)
#		gc.DrawLines([(0,0), (width,0), (height,0)])
#		event.Skip()

	def AcceptsFocus(self):
		return False

	def GetDefaultAttributes(self):
		return wx.BookCtrlBase.GetClassDefaultAttributes()

	def AddPage(self, page, text, select=False, imageId=-1):
		if not page.Reparent(self._bgwnd):
			print "AddPage: false"
			return False
#		page.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
#		page.SetBackgroundColour(wx.GREEN)
#		page.Bind(wx.EVT_PAINT, self._OnPaintPage)
		print "AddPage: true"
##		if not self._items:
##			select = True
		self._items.append((page, text, imageId))
		self._updated = True
		wx.CallAfter(self.DoLayout)
#		self.Refresh()
		if select:
			self.SetSelection(-1)
		elif self._curidx == -1:
			self._curidx = 0
		return True
	
	def InsertPage(self, n, page, text, select=False, imageId=-1):
		if not page.Reparent(self._bgwnd):
			return False
		self._items.insert(n, (page, text, imageId))
		self._updated = True
		wx.CallAfter(self.DoLayout)
#		self.Refresh()
		if select:
			self.ChangeSelection(n)
		elif self._curidx == -1:
			self._curidx = 0
		return True
	
	def DeletePage(self, n):
		page, text, imageid = self._items[n]
		page.Destroy()
		del self._items[n]
		self._updated = True
		wx.CallAfter(self.DoLayout)
		if self._curidx > n or self._curidx == len(self._items):
			self._curidx -= 1
		# XXX need to send page change events
	
	def RemovePage(self, n):
		del self._items[n]
		self.Refresh()

	def DeleteAllPages(self):
		for page, text, imageid in self._items:
			page.Destroy()
		del self._items[:]
		self._updated = True
		wx.CallAfter(self.DoLayout)
		self._curidx = -1

	def ChangeSelection(self, n):
		if n < 0:
			n += len(self._items)
		if n < 0 or n >= len(self._items):
			raise ValueError("index out of range")
		if n == self._curidx:
			return
		if self._oldidx is not None:
			event = SlidebookEvent(EVT_SLIDEBOOK_PAGE_CHANGING.typeId, self.GetId(), n, self._curidx)
			self.EventHandler.ProcessEvent(event)
			if not event.IsAllowed():
				return
#		if self._curidx == -1:
#			self._curidx = 0
		assert self._curidx >= 0
		ticks = abs(n - self._curidx) * self.TIMER_DELAY / self.TIMER_INTERVAL
		self._curidx = n
		self._curpos = wx.Point2D(*self._bgwnd.Position)
		self._dstpos = wx.Point2D(*self._spacing) * -n
		self._incpos = (self._dstpos - self._curpos) / ticks
		self._dstpos = self._dstpos.Rounded
		self._timer.Start(self.TIMER_INTERVAL)
		self.UpdateUI()
	
	def AdvanceSelection(self, forward=True):
		if forward:
#			if self._curidx < len(self._items) - 1:
				self.SetSelection(self._curidx + 1)
		else:
#			if self._curidx > 0:
				self.SetSelection(self._curidx - 1)
	
	def GetSelection(self):
		return self._curidx
	def SetSelection(self, n):
		self._oldidx = self._curidx
		self.ChangeSelection(n)
	Selection = property(GetSelection, SetSelection)
	
	def GetCurrentPage(self):
		page, text, imageid = self._items[self._curidx]
		return page
	CurrentPage = property(GetCurrentPage)
	
	def GetPageCount(self):
		return len(self._items)
	PageCount = property(GetPageCount)
	
	def IsVertical(self):
		return bool(self._style & wx.VERTICAL)
	
	def GetPage(self, n):
		page, text, imageid = self._items[n]
		return page
	
	def GetPageText(self, n):
		page, text, imageid = self._items[n]
		return text
	def SetPageText(self, n, strText):
		page, text, imageid = self._items[n]
		self._items[n] = page, strText, imageid
		self.Refresh()
		return True
	
	def GetPageImage(self, n):
		page, text, imageid = self._items[n]
		return imageid
	def SetPageImage(self, n, imageId):
		page, text, imageid = self._items[n]
		self._items[n] = page, text, imageId
		self.Refresh()
		return True

	def AssignImageList(self, imageList):
		self._imagelst = imageList
		self.Refresh()
	def GetImageList(self):
		return self._imagelist
	def SetImageList(self, imageList):
		self._imagelst = imageList
		self.Refresh()
	ImageList = property(GetImageList, SetImageList)
	
#	def GetControlMargin(self):
#		return self._margin
#	def SetControlMargin(self, margin):
#		self._margin = margin
#		self.OnSize()
#	ControlMargin = property(GetControlMargin, SetControlMargin)
	
#	def GetInternalBorder(self):
#		return self._border
#	def SetInternalBorder(self, internalBorder):
#		self._border = internalBorder
#		self.OnSize()
#	InternalBorder = property(GetInternalBorder, SetInternalBorder)
	
	def HitTest(self, pt):
		raise NotImplementedError
	def CalcSizeFromPage(self, sizePage):
		raise NotImplementedError
	def SetPageSize(self, size):
		raise NotImplementedError
	def GetFitToCurrentPage(self):
		raise NotImplementedError
	def SetFitToCurrentPage(self, fit):
		raise NotImplementedError
	FitToCurrentPage = property(GetFitToCurrentPage, SetFitToCurrentPage)
	


	#def Draw(self, dc):
	#	print 'Draw'
	#	gc = wx.GraphicsContext.Create(dc)
	#	count = len(self._panels)
	#	wpad = self._gutter + 2*self._border
	#	hpad = self._gutter + self._border
	#	panelsz = self.Size - (2*wpad, 2*hpad)
	#	self.VirtualSize = (count*(self.Size.width - wpad) + wpad, self.Size.height)
	#	print self.Size, self.VirtualSize
	#	x, y = hpad, self._gutter
	#	rectsz = panelsz + (2*self._border, 2*self._border)
	#	brush = wx.Brush('blue', wx.SOLID)
	#	dc.SetBackground(brush)
	#	dc.Clear()
	#	brush = wx.Brush('green', wx.SOLID)
	#	gc.SetBrush(brush)
	#	pen = wx.Pen('red', 1, wx.SOLID)
	#	gc.SetPen(pen)
	#	for idx in range(count):
	#		gc.DrawRoundedRectangle(x, y,  rectsz.width, rectsz.height, self._gutter*2)
	#		x += rectsz.width + self._gutter
	#def OnMouseClick(self, event):
	#	self.ScrollWindow(-20, 0)

from wx.lib.msgpanel import MessagePanel

class TestPanel(wx.Panel):
	def __init__(self, parent, data, id=-1, pos=wx.DefaultPosition, 
				 size=wx.DefaultSize, style=0):
		wx.Panel.__init__(self, parent, id, pos, size, style)
		sizer = wx.BoxSizer()
		text = wx.StaticText(self, -1, data)
		sizer.Add(text, 0, wx.ALL, 40)
#		sizer.Add(text, 1, wx.EXPAND | wx.ALL, 30)
		self.SetSizer(sizer)

class SessionPanel(wx.Panel):
	def __init__(self, session, parent, id=-1, pos=wx.DefaultPosition, 
				 size=wx.DefaultSize, style=wx.TAB_TRAVERSAL|wx.NO_BORDER, name='SessionPanel'):
		wx.Panel.__init__(self, parent, id, pos, size, style, name)
		nfont = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL)
		bfont = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
		vsizer = wx.StaticBoxSizer(wx.StaticBox(self), wx.VERTICAL)
		text = wx.StaticText(self, -1, session.title)
		text.SetFont(bfont)
		vsizer.Add(text, 0, wx.EXPAND | wx.ALL, 5)
		text = wx.StaticText(self, -1, session.owner)
		text.SetFont(nfont)
		vsizer.Add(text, 0, wx.EXPAND | wx.ALL, 5)
		recur = session.recur or 'today'
		if recur == 'unknown': recur = '*'
		timeval = '{} - {} {}'.format(session.start.strftime('%H:%M'), session.stop.strftime('%H:%M'), recur)
		text = wx.StaticText(self, -1, timeval)
		text.SetFont(nfont)
		vsizer.Add(text, 0, wx.EXPAND | wx.ALL, 5)
		hsizer = wx.BoxSizer(wx.HORIZONTAL)
		recroom = None
		for room in session.rooms:
			if room.endswith('(Recorder)'):
				recroom = room[:-11]
				continue
			style = wx.BORDER_THEME if room == recroom else 0
			text = wx.StaticText(self, -1, room, style=style)
			hsizer.Add(text, 0, wx.ALL, 2)
		vsizer.Add(hsizer, 0, wx.EXPAND | wx.ALL, 5)
		self.SetSizer(vsizer)
		self.Layout()

class MyFrame(wx.Frame):

	def __init__(self, parent):
#		wx.Frame.__init__(self, parent, -1, "GUI Test", style=wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN|wx.TAB_TRAVERSAL) #, size=(800,600))
		wx.Frame.__init__(self, parent, -1, "GUI Test", style=wx.DEFAULT_FRAME_STYLE) #, size=(800,600))
		self.SetSizeHintsSz(wx.Size(-1, -1), wx.Size(600, 900))
		self.SetExtraStyle(wx.FRAME_EX_CONTEXTHELP)
		panel = wx.Panel(self)
		vsizer = wx.BoxSizer(wx.VERTICAL)
		hsizer = wx.BoxSizer(wx.HORIZONTAL)
		label = wx.StaticText(panel, -1, "Room:")
		hsizer.Add(label, 0, wx.ALL, 5)
		input = wx.TextCtrl(panel, -1)
		hsizer.Add(input, 1, wx.ALL, 5)
		rbutton = wx.Button(panel, -1, "Register")
		hsizer.Add(rbutton, 0, wx.ALL, 5)
		fbutton = wx.Button(panel, -1, "Fetch")
		hsizer.Add(fbutton, 0, wx.ALL, 5)
		vsizer.Add(hsizer, 0, wx.EXPAND, 5)
		
#		dispanel = wx.Panel(panel, size=(400, 400))
#		dispanel.SetSizeHintsSz(wx.Size(-1, -1), wx.Size(400, 400))
#		vsizer.Add(dispanel)
		
		self.myctrl = SlideBook(panel,style=wx.BORDER_STATIC) #, size=(80,50))
		for item in 'one', 'two', 'three':
#			p = MessagePanel(self.myctrl, item, item)
			p = TestPanel(self.myctrl, item, style=wx.TRANSPARENT_WINDOW)
			self.myctrl.AddPage(p, item)
#		self.myctrl.AssignItems([{'data':item} for item in 'one', 'two', 'three'])
		vsizer.Add(self.myctrl, 3, wx.EXPAND | wx.ALL, 5)
		
		output = wx.TextCtrl(panel, -1, style=wx.TE_READONLY | wx.TE_MULTILINE)
		vsizer.Add(output, 2, wx.EXPAND | wx.ALL, 5)
		panel.SetSizer(vsizer)
		panel.Layout()

		self.input = input
		self.output = output
#		self.dispanel = dispanel
		self.schedcli = rpc.SyncRpcClient(sched_addr, content_mgr, 10)
#		self.schedcli = rpc.AsyncRpcClient(sched_addr, content_mgr, self.DoCliNotify, 10)
		self.listnsrv = rpc.AsyncRpcServer(my_addr, content_mgr, self.DoAsyncNotify, 20)
		self.listnsrv.update_schedule = self.OnUpdateSchedule
		rbutton.Bind(wx.EVT_BUTTON, self.OnRegister)
		fbutton.Bind(wx.EVT_BUTTON, self.OnFetch)
		self.Bind(EVT_ASYNC_NOTIFY, self.OnAsyncNotify)
		self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
		print 'init!', threading.current_thread().name, threading.current_thread().ident

	def OnCloseWindow(self, evt):
		print 'OnCloseWindow', threading.current_thread().name, threading.current_thread().ident
		self.listnsrv.close()
		self.schedcli.close()
		self.Destroy()

	def OnFetch(self, evt):
		room = self.input.Value
		print "OnFetch", room, threading.current_thread().name, threading.current_thread().ident
		sched = self.schedcli.scheduler.fetch_schedule(room)
		print "returned:", sched
		if sched:
			self.output.Value = '\n'.join([str(item) for item in sched])
			self.myctrl.AssignItems([{'session':item} for item in sched])
#			pn = SessionPanel(sched[0], self.dispanel, size=(300, 200), style=wx.BORDER_THEME)

	def OnRegister(self, evt):
		room = self.input.Value
		print "OnRegister", room, threading.current_thread().name, threading.current_thread().ident
		self.schedcli.scheduler.register(room, my_addr)

	def OnUpdateSchedule(self, sched):
		print "OnUpdateSchedule", threading.current_thread().name, threading.current_thread().ident
		self.output.Value = sched and '\n'.join([str(item) for item in sched]) 

	def DoCliNotify(self, client, path, result, success):
		print "DoCliNotify", client, path, result, success, threading.current_thread().name, threading.current_thread().ident
		
	def DoAsyncNotify(self, callback):
		print "DoAsyncNotify", threading.current_thread().name, threading.current_thread().ident
#		evt = AsyncNotifyEvent(callback)
		evt = wx.PyEvent(eventType=EVT_ASYNC_NOTIFY.typeId)
		evt.callback = callback
		wx.PostEvent(self, evt)

	def OnAsyncNotify(self, evt):
		print "OnAsyncNotify", threading.current_thread().name, threading.current_thread().ident
		evt.callback()

#----------------------------------------------------------------------

def main():
	global sched_addr, my_addr
	sched_addr = '134.50.150.173:5591'
	my_addr = 'localhost:8080'
	app = wx.PySimpleApp()
	frame = MyFrame(None)
	frame.Show(True)
	app.MainLoop()
	
if __name__ == '__main__':
	main()
